\chapter{Tabular Data Stream}
\label{ap:tds}

O \emph{Tabular Data Stream} (TDS) é um protocolo da camada aplicação utilizado para transferir informação entre um servidor de base de dados e um cliente \cite{MSTDS,SYBASETDS}. Foi desenhado e desenvolvido em 1984 pela Sybase Inc. para ser utilizado no servidor SQL da empresa, e mais tarde foi também desenvolvido pela Microsoft para ser utilizado no Microsoft SQL Server \cite{ENOTETDS}.

\section{Mensagens}
Como qualquer protocolo de rede, o TDS efectua a comunicação usando troca de mensagens. Existem duas categorias de mensagens: mensagens do cliente e mensagens do servidor.

Resumidamente as \textbf{mensagens do cliente} são:
\begin{description}
  \item[Pre-login] \hfill \\
  \emph{Handshake} que tem de ocorrer antes do \emph{login}, e que configura alguns parâmetros tais como a encriptação.
  \item[Login] \hfill \\
  Mensagem que inicia o estabelecimento da comunicação com o servidor. Como resposta, o servidor informa o cliente se aceitou ou rejeitou o pedido de comunicação.
  \item[SQL Command] \hfill \\
  Mensagem que na zona de dados contém um comando SQL ou \emph{batch} de comandos SQL, representado numa \emph{String} codificada em Unicode \cite{UNICODE}.
  \item[SQL Command com Dados Binários] \hfill \\
  Mensagem que faz um pedido de execução de uma operação \emph{\gls{bulkinsert}} usando um comando SQL seguido de dados binários. O comando também é representado numa \emph{String} codificada em Unicode.
  \item[Remote Procedure Call (RPC)] \hfill \\
  Mensagem que faz um pedido de execução de um \emph{\gls{storedprocedure}} ou uma \emph{\glssymbol{udf}}. A mensagem contém o nome, opções e parâmetros do RPC.
  \item[Attention signal] \hfill \\
  Mensagem que cancela a execução de um comando.
\end{description}

\hfill

Resumidamente as \textbf{mensagens do servidor} são:
\begin{description}
  \item[Pre-login response] \hfill \\
  Resposta a uma mensagem de \emph{pre-login}.
  \item[Login response] \hfill \\
  Resposta a uma mensagem de \emph{login}. Contém informação sobre as características do servidor, informação opcional e mensagens de erro.
  \item[Row data] \hfill \\
  Resposta com os dados devolvidos pela execução de um comando. Esta mensagem é precedida por uma descrição dos nomes das colunas e dos tipos de dados.
  \item[Return status] \hfill \\
  Resposta com o valor do estado de um RPC. Também é usada para enviar o estado do resultado da execução de uma instrução T-SQL.
  \item[Return parameters] \hfill \\
  Resposta com os valores dos parâmetros de saída de um RPC.
  \item[Response completion] \hfill \\
  Resposta que indica o fim de um conjunto de resultados.
  \item[Error e Info] \hfill \\
  Resposta que transmite mensagens de erro ou mensagens informativas.
  \item[Attention Acknowledgment] \hfill \\
  Resposta que confirma a recepção de um cancelamento de execução de um comando.
\end{description}

\section{Pacotes}
Cada mensagem é constituída por um ou mais pacotes. Cada pacote tem um tamanho máximo cujo valor é determinado na mensagem de \emph{login}. Todos os pacotes da mensagem excepto o último têm de ter um tamanho igual ao valor do tamanho máximo negociado. Cada pacote é constituído por um cabeçalho (\emph{packet header}) e por uma zona de dados (\emph{packet data}).

\subsection{Cabeçalho} 
\hfill

Corresponde aos primeiros \textbf{8 bytes} do pacote. Os campos do cabeçalho estão representados na seguinte tabela. O valor em cima de cada campo indica o número de bytes desse campo.

\begin{table}[H]
  \caption{Campos do cabeçalho TDS}
  \label{tab:header-fields}
  \centering
\begin{tabular}{ *{6}{p{1.5cm}}}
  1 & 1 & 2 & 2 & 1 & 1
\end{tabular}
\\
\begin{tabular}{| p{1.5cm} *{4}{| p{1.5cm} } | p{1.5cm} |}
  \hline
  Type & Status & Length & SPID & PacketId & Window \\ \hline
\end{tabular}
\end{table}

\textbf{Descrição dos campos do cabeçalho}:
\begin{description}
  \item[Type] \hfill \\
  Define o tipo de mensagem.
  \item[Status] \hfill \\
  Indica o estado da mensagem (por exemplo, indica se a mensagem terminou).
  \item[Length] \hfill \\
  Indica o tamanho do pacote (incluindo o tamanho do cabeçalho).
  \item[SPID] \hfill \\
  Identifica o ID do processo no servidor correspondente à ligação actual. Este campo tem carácter opcional, pelo que nesta implementação será sempre enviado o valor \texttt{0x0000}.
  \item[PacketID] \hfill \\
  Indica o número do pacote. Cada pacote enviado incrementa este valor em uma unidade.
  \item[Window] \hfill \\
  Actualmente não é utilizado, por isso tem sempre o valor \texttt{0x00}.
\end{description}

\textbf{NOTA:} Todos os valores são representados em \emph{network byte order (big-endian)} e são valores sem sinal.

\subsection{Zona de dados}
\hfill

Todos os tipos de mensagens, exceptuando a \emph{Attention signal}, a seguir ao cabeçalho têm uma zona de dados \cite{TDSType}.

\textbf{NOTA:} A zona de dados também pode ser denominada de \emph{data stream} ou apenas \emph{stream}.

Os pacotes tem um tamanho máximo, cujo valor é determinado no \emph{login}. O tamanho do pacote inclui o tamanho do cabeçalho. 

Se uma mensagem produzir um pacote que ultrapasse o tamanho definido, terá de ser dividida por múltiplos pacotes. Cada um desses pacotes terá um cabeçalho semelhante, exceptuando os campos \emph{Status} e \emph{Length}. O campo \emph{Status} terá o valor \texttt{0x0} se houverem mais pacotes da mensagem e terá o valor \texttt{0x1} se o pacote é o último da mensagem. O campo \emph{Length} terá um valor igual ao tamanho definido, para todos os pacotes excepto para o último da mensagem.

Existem dois tipos de zonas de dados: \textbf{\emph{Token Stream}} e \textbf{\emph{Tokenless Stream}}. Um \emph{token stream} é constituído por um ou mais \emph{tokens}, em que cada um deles é seguidos pelos dados relativos ao \emph{token}. Um \emph{tokenless stream} contém directamente os dados da mensagem, sem recorrer a \emph{tokens} para os descrever.

Na tabela a seguir temos um resumo das mensagens que usam \emph{tokens} e as que não usam.

\begin{table}[H]
  \caption{Indicação das mensagens que usam \emph{tokens}}
  \label{tab:token-vs-tokenless}
  \centering
\begin{tabular}{*{3}{| l } |}
  \hline
  \head{Mensagem} & \head{Origem} & \head{Token} \\ \hline
  Pre-Login                   & Cliente & Não \\ \hline
  Login                       & Cliente & Não \\ \hline
  SQL Batch                   & Cliente & Não \\ \hline
  Bulk Load                   & Cliente & Sim \\ \hline
  Remote Prodecure Call       & Cliente & Sim \\ \hline
  Attention                   & Cliente & Não \\ \hline
  Transaction Manager Request & Cliente & Não \\ \hline
  Pre-Login Response          & Servidor & Não \\ \hline
  Login Response              & Servidor & Sim \\ \hline
  Row Data                    & Servidor & Sim \\ \hline
  Return Status               & Servidor & Sim \\ \hline
  Return Parameters           & Servidor & Sim \\ \hline
  Response Completion         & Servidor & Sim \\ \hline
  Error and Info Messages     & Servidor & Sim \\ \hline
  Attention Acknowledgment    & Servidor & Não \\ \hline
\end{tabular}
\end{table}

A definição da gramática dos \emph{streams} (\emph{token} e \emph{tokenless}) é especificada usando \emph{Augmented Backus-Naur Form} \cite{RFC4234}.

\section{\emph{Tokenless Streams}}
\hfill

Um \emph{tokenless stream} contém directamente os dados da mensagem, sem recorrer a \emph{tokens} para os descrever.

A seguir é descrito o formato da zona de dados, das mensagens com \emph{tokenless streams}.

\subsection{Pre-Login}

O \emph{stream} desta mensagem é constituído por uma sequência de opções seguidas dos dados relativos a essas opções. Cada opção tem três campos: \emph{Type}, \emph{Position} e \emph{Length}. \emph{Type} identifica a opção, \emph{Position} indica a posição que a opção ocupa nos dados e \emph{Length} indica o número de bytes que opção ocupa nos dados.

\begin{table}[H]
  \caption{Opções da mensagem de Pre-Login}
  \label{tab:pre-login-options}
  \centering
\begin{tabular}{*{3}{| l } |}
  \hline
  \head{Opção} & \head{Valor} & \head{Descrição} \\ \hline
  \texttt{VERSION}     & \texttt{0x00} & Versão do remetente. Normalmente usado para \emph{debugging}. \\ \hline
  \texttt{ENCRYPTION}  & \texttt{0x01} & Negociar encriptação. \\ \hline
  \texttt{INSTOPT}     & \texttt{0x02} & Nome da instância do SQL Server. \\ \hline
  \texttt{THREADID}    & \texttt{0x03} & Id do thread da aplicação cliente. Usado para \emph{debugging}. \\ \hline
  \texttt{TERMINATOR}  & \texttt{0xFF} & Assinala o fim da mensagem de Pre-Login. \\ \hline
\end{tabular}
\end{table}

Do que se conseguiu apurar apenas \texttt{VERSION} e \texttt{ENCRYPTION} são obrigatórios, e uma vez que as restantes opções de momento são irrelevantes, os pacotes de Pre-Login do driver só irão conter estas duas opções. Para além disso, ainda não será considerada a utilização de encriptação.

\subsection{Login}

Este \emph{stream} define as regras de autenticação entre o cliente e o servidor. O seu tamanho não deve ultrapassar os 128-1 bytes.

A definição deste \emph{stream} possui várias regras que podem ser consultadas em \cite{TDSLOGIN7}, das quais se destacam a \emph{OffsetLength} e a \emph{Data}. Estas duas regras definem os parâmetros concretos do login, tais como a base de dados a utilizar ou o nome de utilizador. A regra \emph{Data} possui os bytes que representam os dados dos parâmetros e a regra \emph{OffsetLength} define a posição e comprimento de cada parâmetro.

\subsection{SQLBatch}

Este \emph{stream} define o formato de uma mensagem SQL Batch.

A definição deste stream é composta por uma regra ALL\_HEADERS{\footnotemark} seguida de um stream em Unicode que contém o comando SQL.
\footnotetext{Alguns streams TDS podem ser precedidos de vários cabeçalhos. A regra ALL\_HEADERS é utilizada para especificar esses cabeçalhos\cite{ALLHEADERS}.}

\section{\emph{Token Streams}}

As mensagens mais complexas (por exemplo, os dados do result set) são construídas usando tokens. Um token consiste num byte que funciona como identificador, seguido de dados específicos ao token.

Existem os seguintes tokens \cite{PacketDataTokenStreams}:

\begin{center}
  \small
  \begin{longtable}{|l|p{10cm}|}
  \caption{Packet Data Token Streams}
  \label{tab:tokenstreams}
  \\ \hline
  \head{Nome} & \head{Descrição}
  \\ \hline
  \endhead
  ALTMETADATA & Descreve o tipo de dados, tamanho e nome da coluna que resulta de uma SQL Statement que gera totais.
  \\ \hline

  ALTROW & Usado para enviar uma linha com totais, cujo formato é descrito pelo token ALTMETADATA.
  \\ \hline

  COLINFO & Descreve a informação da coluna em Browse Mode \cite{BrowseMode}, sp\_cursoropen e sp\_cursorfetch.
  \\ \hline

  COLMETADATA & Descreve o result set para interpretação dos tokens ROW que lhe seguem.
  \\ \hline

  DONE & Indica que uma SQL Statement foi terminada.
  \\ \hline

  DONEINPROC & Indica que uma SQL Statement de um stored procedure foi terminada.
  \\ \hline

  DONEPROC & Indica que um stored procedure terminou.
  \\ \hline

  ENVCHANGE & Notificação de uma alteração de ambiente (por exemplo, base de dados, língua).
  \\ \hline

  ERROR & Usado para enviar uma mensagem de erro ao cliente.
  \\ \hline

  INFO & Usado para enviar uma mensagem de informação ao cliente.
  \\ \hline

  LOGINACK & Usado para enviar ao cliente a resposta a um pedido de login. A ausência deste token numa resposta de login significa que o login no servidor não foi realizado com sucesso.
  \\ \hline

  NBCROW & Usado para enviar ao cliente uma linha definida pelo token COLMETADATA com compressão \emph{null bitmap} (mais informações em \cite{NBCROW}.
  \\ \hline

  OFFSET & Usado para informar o cliente da posição onde uma palavra-chave ocorre num SQL text buffer do próprio cliente. Este token foi removido no TDS 7.2.
  \\ \hline

  ORDER & Usado para informar o cliente que colunas determinam a ordem dos dados.
  \\ \hline

  RETURNSTATUS & Usado para enviar ao cliente o valor do estado de um RPC.
  \\ \hline

  RETURNVALUE & Usado para enviar ao cliente o valor de retorno de um RPC.
  \\ \hline

  ROW & Usado para enviar ao cliente uma linha completa, que foi anteriormente definida por um token COLMETADATA.
  \\ \hline

  SSPI & Token SSPI devolvido durante o processo de login.
  \\ \hline

  TABNAME & Usado para enviar ao cliente o nome da tabela quando sp\_cursoropen é utilizado ou quando em \emph{browser mode}.
  \\ \hline

  TVP ROW & Usado para enviar uma linha \emph{table value parameter} (TVP), do cliente para o servidor.
  \\ \hline
  \end{longtable}
\end{center}
